0%

Java 8 Optional

How to use optional in your project?

Recently, I read some articles and watch videos online and found something.

The following summary is referenced from Optional - The Mother of All Bikesheds by Stuart Marks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
public class Main {
@Setter
@Getter
private List<Customer> customers;

{
Stream<Customer> stream = Stream.of(new Customer(1, "Allen"), new Customer(2, "Tom"));
customers = stream.collect(Collectors.toList());
}

public static void main(String[] args) {
System.out.println("Hello World!");

customerNameByMap();

// Configuration configuration = new Configuration(null);
// getConfigurationByFilter(configuration);

streamOfOptional();

showIdentitySensitiveOperations();
}


/**
* Rule #1 Never, ever, use null for an Optional variable or return value
* This is safe, but hardly any better than checking for null
*
* @param customerList: customer
* @return customer
*/
public static Customer customerNameByID(List<Customer> customerList) {
int customerID = 1;
Optional<Customer> opt = customerList.stream()
.filter(c -> c.getId() == customerID)
.findFirst();
// here same as returning null
return opt.get();
}


/**
* Rule #2 Never use Optional.get() unless you can prove that the Optional is present
* This is safe, but hardly any better than checking for null
*
* @param customerList: customer
* @param customerID: customer's identity
* @return customer's name
*/
public static String customerNameByID(List<Customer> customerList, int customerID) {
Optional<Customer> opt = customerList.stream()
.filter(c -> c.getId() == customerID)
.findFirst();
return opt.isPresent() ? opt.get().getName() : "UNKNOWN";
}

/*
* Rule #3 Prefer alternatives to Optional.isPresent() and Optional.get()
*/

/**
* continued Rule #3 Prefer alternatives to Optional.isPresent() and Optional.get()
*/
public static String customerNameByMap() {
Customer customer = null;

// assume data happens to be null in the executing context
Optional<Customer> opt = Optional.ofNullable(customer);

// orElse(supplier)
Customer data1 = opt.orElse(Customer.DEFAULT_DATA);
System.out.println(data1);

// orElseGet(supplier)
Customer data2 = opt.orElseGet(Customer::new);
System.out.println(data2);

// orElseThrow(ex_supplier)
try {
Customer data3 = opt.orElseThrow(IllegalStateException::new);
} catch (IllegalStateException e) {
// pass
}

// orElse() can be chained directly off the result of the map() call to extract the value if present,
// or the default
return opt.map(Customer::getName).orElse("UNKNOWN");
}


// continued Rule #3: filter
public static void getConfigurationByFilter(Configuration configuration) {

// bad
// Optional<Configuration> oparent = configuration.parent();
// if (!oparent.isPresent() || oparent.get() != configuration) {
// throw new IllegalArgumentException();
// }

// better
configuration.parent()
.filter(config -> config == configuration)
.orElseThrow(IllegalArgumentException::new);
}

private static Optional<Task> getTask() {
return Optional.ofNullable(new Task());
}

// continued Rule #3: IfPresent
public static void showExampleAPIIfPresent() {
Optional<Task> oTask = getTask();
ExecutorService executor = Executors.newSingleThreadExecutor();
// bad
// if (oTask.isPresent()) {
//
// executor.submit(oTask.get());
// }

// better
getTask().ifPresent(executor::submit);
}

// continued Rule #3: streamOfOptional
public static void streamOfOptional() {
// list of customer's id -> list of customers
List<Integer> customersIDList = Stream.of(1, 2, 3).collect(Collectors.toList());
List<Customer> list = customersIDList.stream()
.map(Customer::findByID)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
System.out.println(list);
}


/**
* continued Rule #3: adapting between null and optional
* Sometimes you need to adapt Optional-using code to code that wants null, or vice-versa
*/
public static void optionalNull() {
// If you have a nullable reference and you need an Optional
// Optional<T> opt = Optional.ofNullable(null);
}

/**
* Rule #4: It is generally a bad idea to create an Optional for the specific purpose of chaining methods
* from it to get a value
*
* @param s: any
* @return : string
*/
public String process(String s) {
// bad: Method Chaining is Cool, but ...
// return Optional.ofNullable(s).orElse("DEFAULT");

// good:
return (s != null) ? s : "DEFAULT";
}

/**
* Rule #5: if an optional chain is nested or has an intermediate result of Optional, it is
* probably too complex.
* <p>
* shortest, cleverest? the most important thing is clearest?
*/
public void showNestedOptional() {
Optional<BigDecimal> first = Optional.of(new BigDecimal(1));
Optional<BigDecimal> second = Optional.of(new BigDecimal(2));

Optional<BigDecimal> result;

// bad
result = first.map(b -> second.map(b::add).orElse(BigDecimal.ZERO));

// good
result = Optional.of(first.orElse(BigDecimal.ZERO).add(second.orElse(BigDecimal.ZERO)));

System.out.println(result);
}

/**
* Rule #6: avoid in fields, method parameters and collections
*/
public void myMethod(Optional<Object> anything) {
// pass
}

/**
* Rule #7: avoid using identity-sensitive operations on Optionals
* say, ==, identity hash code, synchronization, serializable
*/
public static void showIdentitySensitiveOperations() {
Optional<Customer> c1 = Optional.of(new Customer(1, "a"));
Optional<Customer> c2 = Optional.of(new Customer(2, "b"));
System.out.println(c1 == c2);

Optional<String> a1 = Optional.of("a");
Optional<String> b1 = Optional.of("b");
System.out.println(a1 == b1);
System.out.println(a1.equals(b1));

Optional<ArrayList<String>> x = Optional.of(new ArrayList<String>());
Optional<ArrayList<String>> y = Optional.of(new ArrayList<String>());
x.get().add(" ");
int result = x.get().size() + y.get().size();
x.get().remove(x.get().size() - 1);
System.out.println(result);
}
}